package com.ht.demo.service.manager.system.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ht.demo.common.appexception.AppErrorCodeEnum;
import com.ht.demo.common.appexception.AppException;
import com.ht.demo.common.page.PageBO;
import com.ht.demo.common.pojo.bo.system.SysDictDataBO;
import com.ht.demo.common.pojo.bo.system.SysDictTypeBO;
import com.ht.demo.common.pojo.bo.system.SysUserBO;
import com.ht.demo.common.pojo.qto.system.SysDictDataQTO;
import com.ht.demo.common.pojo.qto.system.SysDictTypeQTO;
import com.ht.demo.dao.domain.system.SysDictDataDO;
import com.ht.demo.dao.domain.system.SysDictTypeDO;
import com.ht.demo.service.convert.system.SysDictDataBeanUtil;
import com.ht.demo.service.convert.system.SysDictTypeBeanUtil;
import com.ht.demo.service.manager.system.SysDictManager;
import com.ht.demo.service.mapper.system.SysDictDataMapper;
import com.ht.demo.service.mapper.system.SysDictTypeMapper;
import com.ht.demo.service.system.UserTokenManager;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @Author hdengxian
 * @Date 2023/5/24 16:44
 */
@Component
public class SysDictManagerImpl implements SysDictManager {
    @Resource
    private SysDictTypeMapper sysDictTypeMapper;
    @Resource
    private SysDictDataMapper sysDictDataMapper;

    @Override
    public boolean saveDictType(SysUserBO user, SysDictTypeBO dictTypeBO) throws AppException {
        SysDictTypeBeanUtil.insertCheckParam(dictTypeBO);
        if (sysDictTypeMapper.countByDictType(dictTypeBO.getDictType()) > 0) {
            throw new AppException("字典类型已被占用");
        }
        dictTypeBO.setCreateBy(user.getUserName());
        dictTypeBO.setCreateTime(new Date());
        SysDictTypeDO insert = SysDictTypeBeanUtil.sysDictTypeBOToDO(dictTypeBO);
        return sysDictTypeMapper.save(insert);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateDictType(SysUserBO user, SysDictTypeBO dictTypeBO) throws AppException {
        if (dictTypeBO == null || dictTypeBO.getSysDictTypeId() == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_ERROR);
        }
        SysDictTypeDO old = sysDictTypeMapper.getById(dictTypeBO.getSysDictTypeId());
        if (old == null) {
            throw new AppException(AppErrorCodeEnum.UPDATE_DATE_NOT_EXISTS);
        }
        if (StringUtils.isNotBlank(dictTypeBO.getDictType()) && !old.getDictType().equals(dictTypeBO.getDictType())) {
            if (sysDictTypeMapper.countByDictType(dictTypeBO.getDictType()) > 0) {
                throw new AppException("字典类型已被占用");
            }
            //同步更新数据表
            updateSyncData(user, dictTypeBO.getDictType(), old.getDictType());
        }
        dictTypeBO.setUpdateBy(user.getUserName());
        dictTypeBO.setUpdateTime(new Date());
        return sysDictTypeMapper.updateById(SysDictTypeBeanUtil.sysDictTypeBOToDO(dictTypeBO));
    }

    /**
     * 当字典类型发送修改时同步更新数据表
     * @param user
     * @param dictType
     * @throws AppException
     */
    private void updateSyncData(SysUserBO user, String dictType, String oldDictType) throws AppException {
        List<SysDictDataBO> dataBOs = findDictDataListByType(oldDictType);
        if (CollectionUtils.isEmpty(dataBOs)) return;
        for (SysDictDataBO data : dataBOs) {
            data.setDictType(dictType);
            updateDictData(user, data);
        }
    }

    @Override
    public boolean deleteDictType(Long sysDictTypeId) throws AppException {
        SysDictTypeDO dictTypeDO = sysDictTypeMapper.getById(sysDictTypeId);

        sysDictTypeMapper.removeById(sysDictTypeId);
        deleteDictDataByType(dictTypeDO.getDictType());

        return true;
    }

    @Override
    public SysDictTypeBO findDictTypeById(Long sysDictTypeId) throws AppException {
        return SysDictTypeBeanUtil.sysDictTypeDOToBO(sysDictTypeMapper.getById(sysDictTypeId));
    }

    @Override
    public PageBO<SysDictTypeBO> findDictTypeForPage(SysDictTypeQTO qto) throws AppException {
        PageBO<SysDictTypeBO> pageBO = new PageBO<>();
        if (qto == null) {
            return pageBO;
        }
        Integer count = sysDictTypeMapper.findForPageCount(qto);
        if (count == null || count <= 0) {
            return pageBO;
        }
        List<SysDictTypeDO> typeDOs = sysDictTypeMapper.findForPage(qto);
        pageBO.setTotal(count);
        pageBO.setData(SysDictTypeBeanUtil.doList2BOList(typeDOs));

        return pageBO;
    }

    //===========================================================================================
    //===========================================================================================

    @Override
    public boolean saveDictData(SysUserBO user, SysDictDataBO dictDataBO) throws AppException {
        SysDictDataBeanUtil.insertCheckParams(dictDataBO);
        if (sysDictDataMapper.countByTypeAndValue(dictDataBO.getDictType(), dictDataBO.getDictValue()) > 0) {
            throw new AppException("统一字典类型下不能有相同的字典键值");
        }
        dictDataBO.setCreateTime(new Date());
        dictDataBO.setCreateBy(UserTokenManager.getInstance().getLoginUser().getNickName());
        return sysDictDataMapper.save(SysDictDataBeanUtil.sysDictDataBOToDO(dictDataBO));
    }

    @Override
    public boolean updateDictData(SysUserBO user, SysDictDataBO dictDataBO) throws AppException {
        if (dictDataBO == null || dictDataBO.getSysDictDataId() == null) {
            throw new AppException(AppErrorCodeEnum.PARAMETER_ERROR);
        }
        SysDictDataDO old = sysDictDataMapper.getById(dictDataBO.getSysDictDataId());
        if (old == null) {
            throw new AppException(AppErrorCodeEnum.UPDATE_DATE_NOT_EXISTS);
        }
        if (StringUtils.isNotBlank(dictDataBO.getDictValue()) && !old.getDictValue().equals(dictDataBO.getDictValue())) {
            if (sysDictDataMapper.countByTypeAndValue(old.getDictType(), dictDataBO.getDictValue()) > 0) {
                throw new AppException("统一字典类型下不能有相同的字典键值");
            }
        }
        dictDataBO.setUpdateBy(user.getUserName());
        dictDataBO.setUpdateTime(new Date());
        return sysDictDataMapper.updateById(SysDictDataBeanUtil.sysDictDataBOToDO(dictDataBO));
    }

    @Override
    public boolean deleteDictDataByType(String dictType) throws AppException {
        LambdaQueryWrapper<SysDictDataDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDictDataDO::getDictType, dictType);
        return sysDictDataMapper.remove(wrapper);
    }

    @Override
    public boolean deleteDictData(String sysDictDataId) throws AppException {
        return sysDictDataMapper.removeById(sysDictDataId);
    }

    @Override
    public SysDictDataBO findDictDataById(String sysDictDataId) throws AppException {
        return SysDictDataBeanUtil.sysDictDataDOToBO(sysDictDataMapper.getById(sysDictDataId));
    }

    @Override
    public List<SysDictDataBO> findDictDataListByType(String dictType) throws AppException {
        LambdaQueryWrapper<SysDictDataDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDictDataDO::getDictType, dictType);
        return SysDictDataBeanUtil.doList2BOList(sysDictDataMapper.list(wrapper));
    }

    @Override
    public PageBO<SysDictDataBO> findDictDataForPage(SysDictDataQTO qto) throws AppException {
        PageBO<SysDictDataBO> pageBO = new PageBO<>();
        if (qto == null) {
            return pageBO;
        }
        Integer count = sysDictDataMapper.findForPageCount(qto);
        if (count == null || count <= 0) {
            return pageBO;
        }
        List<SysDictDataDO> doList = sysDictDataMapper.findForPage(qto);
        pageBO.setTotal(count);
        pageBO.setData(SysDictDataBeanUtil.doList2BOList(doList));

        return pageBO;
    }
}
